<script lang="tsx" setup>
import { computed, reactive, ref, watch } from 'vue';
import { type FormRules } from 'naive-ui';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import type { PackageVO } from '@/service/types/tenant';
import type { MenuTreeOption } from '@/service/types/system';
import { fetchGetMenuTree, getPackageMenuTreeselect } from '@/service/api/system/menu';
import { addPackage, editPackage, getPackage } from '@/service/api/tenants/package';
type Model = Pick<PackageVO, 'packageId' | 'packageName' | 'menuIds' | 'menuCheckStrictly' | 'remark'>;
interface Props {
  operateType: NaiveUI.TableOperateType;
  currentId?: string | number | null | unknown;
}
const treeLoading = ref<boolean>(false);
const loading = ref(false);
interface Emits {
  (e: 'submitted'): void;
}
const selectChecKeys = ref<number[]>([]);
const menus = ref<MenuTreeOption[]>([]);
const show = ref<boolean>(false);
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
defineOptions({
  name: 'PckageForm'
});
const { formRef, validate, restoreValidation } = useNaiveForm();
const { createRequiredRule } = useFormRules();
const rules: FormRules = {
  clientKey: {
    required: true,
    message: '客户端key不能为空',
    trigger: 'blur'
  },
  clientSecret: {
    required: true,
    message: '客户端秘钥不能为空',
    trigger: 'blur'
  },
  deviceType: createRequiredRule('设备类型不能为空'),
  grantTypeList: createRequiredRule('授权类型不能为空'),
  status: {
    required: true,
    message: '请选择状态',
    trigger: 'blur'
  }
};
const selectAllRef = ref<boolean>(false);
const title = computed(() => {
  const titles: Record<NaiveUI.TableOperateType, string> = {
    add: '新增套餐',
    edit: '修改套餐'
  };
  return titles[props.operateType];
});
const visible = defineModel<boolean>('visible', {
  default: false
});
const currentModelData = ref<PackageVO>();
const model: Model = reactive(createDefaultModel());
const allMenuIds = ref<number[]>([]);

function createDefaultModel(): Model {
  return {
    packageId: '',
    packageName: '',
    menuIds: '',
    menuCheckStrictly: false,
    remark: ''
  };
}
const getAllIds = (data: MenuTreeOption[]): number[] => {
  const ids: number[] = [];
  const traverse = (obj: MenuTreeOption): void => {
    ids.push(obj.id as number);
    if (obj.children) {
      // 确保 children 存在
      obj.children.forEach(child => traverse(child));
    }
  };
  data.forEach(item => traverse(item));
  return ids;
};
const getPackageById = async (id: number) => {
  show.value = true;
  const { error, data } = await getPackage(id);
  if (!error) {
    // @ts-expect-error 忽略Request请求
    currentModelData.value = data?.data;
  }
  show.value = false;
};
const getMenuTree = async () => {
  treeLoading.value = true;
  const { data, error } = await getPackageMenuTreeselect(props.currentId as number);
  treeLoading.value = false;
  if (!error) {
    // @ts-expect-error 忽略Request请求
    const menusData = data?.data?.menus;
    const ids = getAllIds(menusData as MenuTreeOption[]);
    allMenuIds.value = ids;
    menus.value = menusData;
    // @ts-expect-error 忽略Request请求
    selectChecKeys.value = data?.data?.checkedKeys;
  }
};
const getAllMenuTree = async () => {
  treeLoading.value = true;
  const { data, error } = await fetchGetMenuTree();
  if (!error) {
    // @ts-expect-error 忽略Request请求
    const ids = getAllIds(data?.data as MenuTreeOption[]);
    allMenuIds.value = ids;
    // @ts-expect-error 忽略Request请求
    menus.value = data?.data;
  }
  treeLoading.value = false;
};
async function handleInitModel() {
  Object.assign(model, createDefaultModel());
  if (props.operateType === 'edit' && props.currentId) {
    await getPackageById(props.currentId as number);
    await getMenuTree();
    Object.assign(model, currentModelData.value);
  } else {
    await getAllMenuTree();
  }
}
watch(visible, () => {
  if (visible.value) {
    handleInitModel();
    restoreValidation();
  }
});

const closeModal = () => {
  visible.value = false;
};
const submitAddPackage = async (params: PackageVO) => {
  const { error, data } = await addPackage(params);
  loading.value = false;
  if (!error) {
    (window as any).$message?.success(data?.msg);
    closeModal();
    emit('submitted');
  }
};
const submitEditPackage = async (params: PackageVO) => {
  const { error, data } = await editPackage(params);
  loading.value = false;
  if (!error) {
    (window as any).$message?.success(data?.msg);
    closeModal();
    emit('submitted');
  }
};
async function handleSubmit() {
  await validate();
  loading.value = true;
  const { ...params } = model;
  params.menuIds = selectChecKeys.value as number[];
  if (!props.currentId) {
    await submitAddPackage(params as PackageVO);
  } else {
    await submitEditPackage({ ...params, packageId: props.currentId } as PackageVO);
  }
}
// 全选
const selectAll = () => {
  if (selectAllRef.value) {
    selectChecKeys.value = [];
    selectAllRef.value = false;
  } else {
    selectChecKeys.value = allMenuIds.value;
    selectAllRef.value = true;
  }
};
const handleSelectKey = (keys: any) => {
  selectChecKeys.value = keys;
};
</script>

<template>
  <NModal v-model:show="visible" :title="title" preset="card" class="w-740px">
    <NSpin :show="show">
      <NForm ref="formRef" :model="model" :rules="rules">
        <NGrid x-gap="12" responsive="screen" item-responsive>
          <NGi span="24 s:24 m:12">
            <NFormItemGi span="24 s:24 m:24" label="租户套餐" path="packageName">
              <NInput v-model:value="model.packageName" placeholder="请输入租户套餐" />
            </NFormItemGi>
            <NFormItemGi span="24 s:24 m:24" label="备注" path="remark">
              <NInput v-model:value="model.remark" type="textarea" placeholder="请输入备注" />
            </NFormItemGi>
          </NGi>
          <NGi span="24 s:24 m:12" class="flex flex-col flex-gap-5px">
            <div class="flex justify-between">
              <div>菜单权限</div>
              <div class="flex flex-gap-5px">
                <NButton size="tiny">展开/折叠</NButton>
                <NButton size="tiny" @click="selectAll">全选</NButton>
              </div>
            </div>
            <div class="flex items-center justify-between pl-8px pr-5px">
              <div class="flex items-center flex-gap-8px">
                <SvgIcon class="font-size-12px" icon="nimbus:arrows-horizontal" />
                <div>父子联动</div>
              </div>
              <NCheckbox v-model:checked="model.menuCheckStrictly" />
            </div>
            <div>
              <NSpin :show="treeLoading">
                <NScrollbar class="h-300px">
                  <NTree
                    block-line
                    :cascade="model.menuCheckStrictly"
                    checkable
                    :selectable="false"
                    checkbox-placement="right"
                    block-node
                    children-field="children"
                    key-field="id"
                    :data="menus"
                    :checked-keys="selectChecKeys"
                    @update:checked-keys="handleSelectKey"
                  >
                    <template #empty>
                      <Empty />
                    </template>
                  </NTree>
                </NScrollbar>
                <!--
    :default-selected-keys="defaultCheckedKeys"
                  :checked-keys="defaultCheckedKeys"
-->
              </NSpin>
            </div>
          </NGi>
        </NGrid>
      </NForm>
    </NSpin>
    <template #footer>
      <NSpace justify="end">
        <NButton @click="closeModal">取消</NButton>
        <NButton type="primary" :loading="loading" @click="handleSubmit">提交</NButton>
      </NSpace>
    </template>
  </NModal>
</template>

<style lang="scss" scoped></style>
